package com.tdkj.util.typeconverter;

import java.lang.reflect.Member;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.opensymphony.xwork2.conversion.TypeConverter;

public class DateTypeConverter implements TypeConverter {

	private static final Logger log = Logger.getLogger(DateTypeConverter.class);
    
    public static final String[] INPUT_DATE_FORMATS = {
    	"yyyy-MM-dd'T'HH:mm:ss",
        "yyyy-MM-dd HH:mm:ss",
        "yyyy-MM-dd HH:mm",
        "yyyy-MM-dd HH",
        "yyyy-MM-dd"
        };
  
    public static final String[] INPUT_DATE_FORMATS_REGEX = {
    	"\\d{4}(-)\\d{2}(-)\\d{2}[T]\\d{2}(:)\\d{2}(:)\\d{2}[+]\\d{2}(:)\\d{2}",
        "\\d{4}(-)\\d{2}(-)\\d{2}\\s\\d{2}(:)\\d{2}(:)\\d{2}",
        "\\d{4}(-)\\d{2}(-)\\d{2}\\s\\d{2}(:)\\d{2}",
        "\\d{4}(-)\\d{2}(-)\\d{2}\\s\\d{2}",
        "\\d{4}(-)\\d{2}(-)\\d{2}"
        };
    
    private static final Map<Pattern,String> INPUT_DATE_FORMATS_REGEX_MAP = new HashMap<Pattern,String>();
    private static final Map<String,ThreadLocal<DateFormat>> INPUT_DATE_FORMATS_STRING_MAP = new HashMap<String,ThreadLocal<DateFormat>>();
    
    static {
    	for(int i=0; i<INPUT_DATE_FORMATS_REGEX.length; i++){
    		Pattern pattern = Pattern.compile(INPUT_DATE_FORMATS_REGEX[i]);
    		INPUT_DATE_FORMATS_REGEX_MAP.put(pattern, INPUT_DATE_FORMATS[i]);
    		INPUT_DATE_FORMATS_STRING_MAP.put(INPUT_DATE_FORMATS[i], new ThreadLocal<DateFormat>());
    	}
    }
    
    
    //多线程问题，DateFormat非线程安全
    private static final DateFormat getDateFormat(Pattern pattern) throws TypeConvertException {
    	String formatString = INPUT_DATE_FORMATS_REGEX_MAP.get(pattern);
    	return getDateFormat(formatString);
    }
    
    public static final DateFormat getDateFormat(String formatString) throws TypeConvertException {
    	
    	ThreadLocal<DateFormat> df = INPUT_DATE_FORMATS_STRING_MAP.get(formatString);
    	if(df == null){
    		throw new TypeConvertException( "日期格式转换不支持 =>" + formatString);
    	}
    	
    	DateFormat dateFormat = df.get();
    	if(dateFormat == null){
    		dateFormat = new SimpleDateFormat(formatString);
    		df.set(dateFormat);
    	}
    	
    	return dateFormat;
    }
    
    public static final String convertToString(Date date, String formatString){
    	String retString = null;
    	try{
    		retString = getDateFormat(formatString).format(date);
    	}catch(TypeConvertException e){
    		log.error(" convert to string failed : " + e.getMessage() , e);
    	}
    	return retString;
    }
    
    public static final Date convertToDate(String dateString){
    	
    	Date date = null;
    	
    	for(Pattern p : INPUT_DATE_FORMATS_REGEX_MAP.keySet()){
    		Matcher matcher = p.matcher(dateString);
			if(matcher.matches()){
				try {
					date = getDateFormat(p).parse(dateString);
				} catch (Exception e) {
					log.error(" convert to date failed : " + dateString , e);
				}
			}
    	}
    	
    	return date;
    }
    
    public DateTypeConverter() {  
    }  

	@Override
	public Object convertValue(Map<String, Object> context, Object target,
			Member member, String propertyName, Object value, Class toType) {
		
		Object toObject = null;
    	
    	if(toType.equals(java.util.Date.class)){
    		
    		if(value instanceof String){
    			String dateString = String.valueOf(value);
    			Object obj = convertToDate(dateString);
    			toObject = obj;
    		}else if(value instanceof String[]){
    			
    			String[] dateStrings = (String[])value;
    			if(dateStrings.length == 1 ){
    				Object obj = convertToDate(dateStrings[0]);
	    			toObject = obj;
    			}else{
	    			Object[] objs = new Date[dateStrings.length];
	    			for(int i=0; i<dateStrings.length; i++){
	    				objs[i] = convertToDate(dateStrings[i]);
	    			}
	    			toObject = objs;
    			}
    		}
    	}else{
    		toObject = value;
    	}
    	
		return toObject;
	}
    

	public static void main(String[] args){
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
			Timestamp time = new Timestamp(System.currentTimeMillis());
			String ss = dateFormat.format(time);
			System.out.println(ss);
			
			dateFormat = SimpleDateFormat.getDateInstance(DateFormat.LONG);
			dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
			try {
				Date date = dateFormat.parse("2012-07-25T12:22:00+08:00");
				date = DateTypeConverter.convertToDate("2012-07-25T18:22:00+08:00");
				System.out.println(dateFormat.format(date));
			} catch (ParseException e) {
				e.printStackTrace();
			}
	}

}
